#include <iostream>			
#include <assert.h>
#include <qtimer.h>			
#include <qudpsocket.h>
#include <tws_debugging.h>	
#include "xinfomatconfigmanager.h"   
#include "xinfomattypeparserfactory.h"
#include "xinfomattypeparserbase.h"
#include <xinifile.h>

//#define _DEBUGING_MANAGER_

const int  TIME_INTERVAL = 1000;
const char INI_SECTION_UDP[] = "";
const char INI_KEY_UDP[] = "UDPPORT";
const char UDPD_CONFIG_FILE [] = "/usr/infomat/udpd.conf";

XInfomatConfigManager::XInfomatConfigManager() :
    m_inDataSize(0),m_outHost(NULL), m_outPort(0),m_xTypeParser(NULL)
{
}

XInfomatConfigManager::~XInfomatConfigManager()
{
	if ( NULL != m_xTypeParser)
	{
		delete m_xTypeParser;
		m_xTypeParser = NULL;
	}
}

/** ******************************************************
 *@brief:   getInDatagram
 *@param:   in_datagram - the datagram from MainWidget
 *			in_datasize - the size of datagram
 *			in_senderIp - sender Ip
 *			in_senderPort - sender port (udpd.conf)
 ********************************************************/
void XInfomatConfigManager::getInDatagram(QByteArray in_datagram, QString in_senderIp )
{
    m_inData  = in_datagram;
	m_outHost = in_senderIp;
   
	XIniFile iniFile;
	assert(0 == iniFile.open (UDPD_CONFIG_FILE));

	int tmpPort;
	if (0 != iniFile.readInt(INI_SECTION_UDP, INI_KEY_UDP, tmpPort)) 
	{
		DEBUG("Canont find port, Please Check Your udpd.conf");
		return ; 
	}
	m_outPort = (quint16)tmpPort;
	iniFile.close();

    assignJobs();
	return;
}

/** ******************************************************
 *@brief: Manager's job scope
 ********************************************************/
void XInfomatConfigManager::assignJobs()
{
	//manager tell haeder parser to analyse header
	//the 'header parser' find out what's the damn type the customer sent.
	m_xinfomatHeadParser.getHeadData(m_inData);

    //manager tell 'type parser' to analyse type and process customer request.
	//manager does not care about what's the damn type.
	//just pass it to 'type parser' to do it, where the 
	//'type parser' is created by factory.
	createTypeParser();		
	
	//manager get result from type parser and send it out.
	//manager doesn't care about what's the damn result,
	//just send it back.
    m_outData = m_xTypeParser->getOutDatagram();
    QTimer::singleShot(TIME_INTERVAL, this, SLOT(slotOutDatagram()));

    return;
}

/** ******************************************************
 *@brief: createTypeParser
 *          the types are the following,
 *             (1)ip type, (2)mac type (3)... 
 ********************************************************/
void XInfomatConfigManager::createTypeParser()
{
    XInfomatTypeParserFactory* xTypeParserFactory = new XInfomatTypeParserFactory();

	// Type Parser Factory create the type parser according to head protocal
	// @see Configuration Head Protocol
    m_xTypeParser = xTypeParserFactory->createTypeParser(m_xinfomatHeadParser.getHeadType());
    
	// After create 'type parser', pass datagram to it
	m_xTypeParser->getResource(m_inData);

	// clean up
	if (NULL != xTypeParserFactory)
	{
		delete xTypeParserFactory;
		xTypeParserFactory = NULL;
	}
	return;
}

/** ******************************************************
 *@brief: slotOutDatagram
 *@param:
 ********************************************************/
void XInfomatConfigManager::slotOutDatagram()
{
	QUdpSocket * udpSocket = new QUdpSocket(this);
    int ret;
    QHostAddress host;
    host.setAddress(m_outHost);

    ret = udpSocket->writeDatagram(m_outData,host, m_outPort);

	delete udpSocket;
	udpSocket = NULL;
    
	if (NULL != m_xTypeParser)
	{
		DEBUG("delete m_xTypeParser");
		delete m_xTypeParser;
		m_xTypeParser = NULL;
	}

#ifdef _DEBUGING_MANAGER_
    DEBUG("Manager Checking ...");
    DEBUG("After sending out data ...");
    for (int i =0; i< m_outData.size(); i++ )
        DEBUG("BYTE %02d,\t(HEX):%02x",i,*(m_outData.data()+i));
    DEBUG ("return bytes :%02d", ret);
#endif

    return;
}
